/****************************************************** 
 *  Copyright 2018 IBM Corporation 
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
 *  you may not use this file except in compliance with the License. 
 *  You may obtain a copy of the License at 
 *  http://www.apache.org/licenses/LICENSE-2.0 
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License.
 */
package com.hyperledger.fabric.sdk3;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.File;
import java.io.FileInputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;
import org.hyperledger.fabric.sdk.ChaincodeID;
import org.hyperledger.fabric.sdk.ChaincodeResponse.Status;
import org.hyperledger.fabric.sdk3.Config;
import org.hyperledger.fabric.sdk3.Util;
import org.hyperledger.fabric.sdk3.client.CAClient;
import org.hyperledger.fabric.sdk3.client.ChannelClient;
import org.hyperledger.fabric.sdk3.client.FabricClient;
import org.hyperledger.fabric.sdk3.user.UserContext;

import cn.hutool.core.util.RandomUtil;

import org.hyperledger.fabric.sdk.Channel;
import org.hyperledger.fabric.sdk.EventHub;
import org.hyperledger.fabric.sdk.Orderer;
import org.hyperledger.fabric.sdk.Peer;
import org.hyperledger.fabric.sdk.ProposalResponse;
import org.hyperledger.fabric.sdk.TransactionProposalRequest;

/**
 * <p> From https://blog.csdn.net/qq_27348837/article/details/95489720
 * @author Balaji Kadambi
 *
 */

public class InvokeChaincode {

	private static final byte[] EXPECTED_EVENT_DATA = "!".getBytes(UTF_8);

	private static final String EXPECTED_EVENT_NAME = "event";

	public static void main(String args[]) {
		try {
			Util.cleanUp();
			UserContext adminUser = new UserContext();
			adminUser.setName(Config.ADMIN);
			adminUser.setAffiliation(Config.ORG1);
			adminUser.setMspId(Config.ORG1_MSP);
			File f = new File(Config.CA1_TLSFILE);
			String certficate = new String(IOUtils.toByteArray(new FileInputStream(f)), "UTF-8");
			Properties properties = new Properties();
			properties.put("pemBytes", certficate.getBytes());
			properties.setProperty("pemFile", f.getAbsolutePath());
			properties.setProperty("allowAllHostNames", "true");
			CAClient caclient = new CAClient(Config.CA1NAME, Config.CA_ORG1_URL, properties);
			caclient.setAdminUserContext(adminUser);
			adminUser = caclient.enrollAdminUserTLS("admin", "adminpw");

			FabricClient fabClient = new FabricClient(adminUser);

			ChannelClient channelClient = fabClient.createChannelClient(Config.CHANNEL_NAME);
			Channel channel = channelClient.getChannel();
			Properties properties1 = Util.gete2ePro("peer", Config.ORG1_PEER_0);
			Peer peer = fabClient.getInstance().newPeer(Config.ORG1_PEER_0, Config.ORG1_PEER_0_URL, properties1);
			Properties properties2 = Util.gete2ePro("peer", Config.ORG2_PEER_0);
			Peer peer2 = fabClient.getInstance().newPeer(Config.ORG2_PEER_0, Config.ORG2_PEER_0_URL, properties2);
			EventHub eventHub = fabClient.getInstance().newEventHub("eventhub01", Config.grpc + Config.baseUrl + ":7053",
			      properties1);
			// EventHub eventHub2 = fabClient.getInstance().newEventHub("eventhub02", "grpcs://"+Config.baseUrl+":9053");
			Properties orderPro = Util.gete2ePro("orderer", Config.ORDERER_NAME);
			Orderer orderer = fabClient.getInstance().newOrderer(Config.ORDERER_NAME, Config.ORDERER_URL, orderPro);
			channel.addPeer(peer);
			channel.addPeer(peer2);// 背书策略为OR的话不需要添加 peer2
			channel.addEventHub(eventHub);
			channel.addOrderer(orderer);
			channel.initialize();

			TransactionProposalRequest request = fabClient.getInstance().newTransactionProposalRequest();

			//ChaincodeID ccid = ChaincodeID.newBuilder().setName(Config.CHAINCODE_1_NAME).build();
			//request.setChaincodeID(ccid);
			//request.setFcn("invoke");			
			//String[] arguments = { "a", "b", "11" };
			//
			ChaincodeID ccid = ChaincodeID.newBuilder().setName("netcon").build();			
			request.setChaincodeID(ccid);
			request.setFcn("create");
			String[] arguments = { RandomUtil.simpleUUID(), "9999999999", "za", "zb", "zaddr", "999", "998" };
			request.setArgs(arguments);
			request.setProposalWaitTime(1000);

			Map<String, byte[]> tm2 = new HashMap<>();
			tm2.put("HyperLedgerFabric", "TransactionProposalRequest:JavaSDK".getBytes(UTF_8));
			tm2.put("method", "TransactionProposalRequest".getBytes(UTF_8));
			tm2.put("result", ":)".getBytes(UTF_8));
			tm2.put(EXPECTED_EVENT_NAME, EXPECTED_EVENT_DATA);
			request.setTransientMap(tm2);
			Collection<ProposalResponse> responses = channelClient.sendTransactionProposal(request);
			for (ProposalResponse res : responses) {
				Status status = res.getStatus();
				Logger.getLogger(InvokeChaincode.class.getName()).log(Level.INFO,
				      "Invoked on " + Config.CHAINCODE_1_NAME + ". Status - " + status);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
